/*
 * UMediaSourceT.h
 *
 *  Created on: 2015年12月31日
 *      Author: terry
 */

#ifndef UMEDIASOURCET_H_
#define UMEDIASOURCET_H_

#include "UMediaSinkArray.h"
#include <string>


template < class T >
class UMediaSourceT : public T
{
public:
	UMediaSourceT():
		m_state(UMEDIA_STATE_STOPPED)
	{
	}

	virtual ~UMediaSourceT()
	{
	}

	virtual const char* getUrl()
	{
        comn::AutoCritSec lock(m_csSource);
		return m_url.c_str();
	}

	virtual bool getMediaFormat(UMediaFormat& fmt)
	{
		comn::AutoCritSec lock(m_csSource);
		if (!m_format.isValid())
		{
			return false;
		}

		fmt = m_format;
		return true;
	}

	virtual int startStream()
	{
		setState(UMEDIA_STATE_PLAYING);
		return 0;
	}

	virtual int pauseStream()
	{
		setState(UMEDIA_STATE_PAUSED);
		return 0;
	}

	virtual void stopStream()
	{
		setState(UMEDIA_STATE_STOPPED);
	}

	virtual void setState(UMediaState state)
	{
		comn::AutoCritSec lock(m_csSource);
		m_state = state;
	}

	virtual int getState()
	{
        comn::AutoCritSec lock(m_csSource);
		return m_state;
	}

	virtual bool addSink(UMediaSink* pSink)
	{
		bool done = m_arrSink.addSink(pSink);
		if (done)
		{
            UMediaFormat format;
            if (getMediaFormat(format))
			{
				pSink->onMediaFormat(format);
			}
		}
		return done;
	}

	virtual void removeSink(UMediaSink* pSink)
	{
		m_arrSink.removeSink(pSink);
	}

	virtual void removeSinks()
	{
		m_arrSink.removeSinks();
	}

	virtual size_t getSinkCount()
	{
		return m_arrSink.getSinkCount();
	}

	virtual int forceKeyFrame()
	{
		return ENOSYS;
	}

	virtual int getDuration()
	{
        comn::AutoCritSec lock(m_csSource);
		return m_format.m_duration;
	}

	virtual bool setScale(float scale)
	{
		return false;
	}

    virtual float getScale()
    {
        return 1.0f;
    }

	virtual bool isSeekable()
	{
		return false;
	}

	virtual bool seek(int64_t pos)
	{
		return false;
	}

	virtual int64_t getTime()
	{
		return 0;
	}


    bool isFormatReady()
    {
        comn::AutoCritSec lock(m_csSource);
        return m_format.isValid();
    }

protected:
	virtual void fireMediaFormat(const UMediaFormat& fmt)
	{
		m_arrSink.fireMediaFormat(fmt);
	}

	virtual void fireMediaPacket(UMediaPacket& pkt)
	{
		m_arrSink.fireMediaPacket(pkt);
	}

	virtual void fireMediaEvent(int event)
	{
		m_arrSink.fireMediaEvent(event);
	}


	void setMediaFormat(const UMediaFormat& fmt)
	{
		comn::AutoCritSec lock(m_csSource);
		m_format = fmt;
	}

	void setVideoFormat(const UMediaFormat& fmt)
	{
		comn::AutoCritSec lock(m_csSource);
		m_format.copyVideo(fmt);
	}

	void setAudioFormat(const UMediaFormat& fmt)
	{
		comn::AutoCritSec lock(m_csSource);
		m_format.copyAudio(fmt);
	}

protected:
	comn::CriticalSection m_csSource;
	std::string m_url;
	UMediaFormat	m_format;
	UMediaState		m_state;
	UMediaSinkArray	m_arrSink;


};


#endif /* UMEDIASOURCET_H_ */
